package hkust.csit5110.android.util;

import java.io.*;

import com.musicg.sound.Wave;
import com.musicg.sound.WaveInputStream;
import com.musicg.sound.timedomain.AmplitudeTimeDomainRepresentation;
import com.musicg.sound.timedomain.FrequencyTimeDomainRepresentation;


//Authorized by Marti-H and maozhu

public class GetFeatures {

	/**
	 * @param args
	 */
	private String fileName;   //The file path
    private double mean;       //The mean of the energy level
	public GetFeatures(String filename) {
		this.fileName = filename;
	}

	private String emotion, gender, voice;
	private InputStream fis = null;
	
    /*
     * Use the mean frequency to classify the gender
     */
	public String getGender() {
		try {
			fis = new FileInputStream(fileName);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		WaveInputStream wis = new WaveInputStream(fis);  //create a wave inputStream by inputStream
		Wave wave = new Wave(wis);  //create a wave object by wave inputStream		
		AmplitudeTimeDomainRepresentation ampRp = new AmplitudeTimeDomainRepresentation(wave);
		FrequencyTimeDomainRepresentation freqRp = new FrequencyTimeDomainRepresentation(wave);  //Time DomainRepresentations
		short[] amplitudes = ampRp.getAmplitudes();
		int count = 0;  //counter
		float numberOfAm = 0;  //total number of amplitudes
		float durationTime = wave.length();  //duration 
		for(int i=0; i<amplitudes.length; i++) {			
			if(amplitudes[i] == 0) {
				count++;
			}
		}
		numberOfAm = count / 3;
		float freq = numberOfAm / durationTime;
		System.out.println("The frequency is "+freq);
		if (freq > 250.0)
			gender = "B";
		else
			gender = "A";
		return gender;
	}
	
    /*
     * The Emotion of the voice
     */
	public String getEmotion() {
		try {
			fis = new FileInputStream(fileName);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		emotion = "A";
		return emotion;
	}

	
	/*
	 * Use the energy level to classify the voice
	 */
	public String getVoice() {
		try {
			fis = new FileInputStream(fileName);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		WaveInputStream wis = new WaveInputStream(fis); // create a wave
														// inputStream by
														// inputStream

		Wave wave = new Wave(wis); // create a wave object by wave inputStream

		AmplitudeTimeDomainRepresentation ampRp = new AmplitudeTimeDomainRepresentation(
				wave);

		short[] amplitudes = ampRp.getAmplitudes();
		double[] norAmplitudes = ampRp.getNormalizedAmplitudes();
		double count = 0.0;

		for (int i = 0; i < amplitudes.length; i++) {

			count = count + Math.abs(norAmplitudes[i]);

		}
		mean = count / (double) (amplitudes.length);

		if (mean < 0.017895451789639368)
			voice = "A";
		else if (mean >= 0.017895451789639368 && mean < 0.0203452)
			voice = "B";
		else if (mean >= 0.0203452 && mean < 0.0389014)
			voice = "C";
		else if (mean >= 0.0389014 && mean < 0.0544634)
			voice = "D";
		else if (mean >= 0.0544634 && mean < 0.030196)
			voice = "E";
		else if (mean >= 0.0730196 && mean < 0.09457)
			voice = "G";
		else if (mean >= 0.09457)
			voice = "H";
		else
			voice = "A";
		System.out.println("The mean is "+mean);
		return voice;
	}
	
	/*
	 * Get the target voice by the D-tree
	 */
	public String getTargetVoice(){
		if(("D".equals(this.voice)) || ("H".equals(this.voice)))
		return "C";
		else if("A".equals(this.voice) || "G".equals(this.voice))
		return "G";
		else if("E".equals(this.voice) || "A".equals(this.voice))
		return "G";
		else if("E".equals(this.voice) || "B".equals(this.voice))
		return "C";
		else if("C".equals(this.voice) || "A".equals(this.voice))
		return "C";
		else return "A";
	}
	
	/*
	 * Get the target Emotion by the D-tree
	 */
	public String getTargetEmotion(){
		if ("E".equals(this.voice)||"D".equals(this.voice)|| "B".equals(this.voice)|| "C".equals(this.voice)||("A".equals(this.emotion)&&("B".equals(this.gender))))
			return "D";
			if ("G".equals(this.voice)|| (("A".equals(this.voice))&& ("A".equals(this.gender))))
				return "B";
			if ("E".equals(this.voice)|| "D".equals(this.voice)|| "B".equals(this.voice)|| "C".equals(this.voice))
				return "D";
			if ("H".equals(this.voice))
				return "C";
			else return "D";

	}
	
	/*
	 * Get the target gender by the D-tree
	 */
    public String getTargetGender(){
    	if("A".equals(this.gender))
    	return "B";
    	if("B".equals(this.gender) && "E".equals(this.voice)|| "G".equals(this.voice)|| "H".equals(this.voice))
    	return "B";
    	if("B".equals(this.gender) &&"D".equals(this.voice)|| "A".equals(this.voice)|| "A".equals(this.voice) || "A".equals(this.voice))
    	return  "B";
    	else return "A";
    }

    
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		GetFeatures gd = new GetFeatures(
				"C:/Users/acer/Desktop/project/record.wav");
	    gd.getEmotion();
	    gd.getGender();
	    gd.getVoice();
	    String s1,s2,s3;
	    s1 = gd.getTargetVoice();
	    s2 = gd.getTargetGender();
	    s3 = gd.getTargetEmotion();
	    System.out.println("TargetVoice is "+s1);
	    System.out.println("TargetGender is "+s2);
	    System.out.println("TargetEmotion is "+s3);
	}
}
